{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## KMeans聚类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "#导入必要的工具包\n",
    "import pandas as pd\n",
    "import numpy as np\n",
    "from sklearn.cluster import MiniBatchKMeans\n",
    "from sklearn.model_selection import train_test_split\n",
    "from sklearn import metrics\n",
    "\n",
    "from sklearn.decomposition import PCA\n",
    "import time\n",
    "\n",
    "from collections import defaultdict\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 1 统计训练集，测试集中有多少不同的用户的events"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "number of uniqueUsers :3391\n",
      "number of uniqueEvents :13418\n"
     ]
    }
   ],
   "source": [
    "uniqueUsers = set()\n",
    "uniqueEvents = set()\n",
    "\n",
    "#倒排表\n",
    "#统计每个用户参加的活动   / 每个活动参加的用户\n",
    "eventsForUser = defaultdict(set)\n",
    "usersForEvent = defaultdict(set)\n",
    "    \n",
    "for filename in [\"train.csv\", \"test.csv\"]:\n",
    "    f = open(filename, 'r')\n",
    "    \n",
    "    #忽略第一行（列名字）\n",
    "    f.readline().strip().split(\",\")\n",
    "    \n",
    "    for line in f:    #对每条记录\n",
    "        cols = line.strip().split(\",\")\n",
    "        uniqueUsers.add(cols[0])   #第一列为用户ID\n",
    "        uniqueEvents.add(cols[1])   #第二列为活动ID\n",
    "        \n",
    "        #eventsForUser[cols[0]].add(cols[1])    #该用户参加了这个活动\n",
    "        #usersForEvent[cols[1]].add(cols[0])    #该活动被用户参加\n",
    "    f.close()\n",
    "\n",
    "\n",
    "n_uniqueUsers = len(uniqueUsers)\n",
    "n_uniqueEvents = len(uniqueEvents)\n",
    "\n",
    "print(\"number of uniqueUsers :%d\" % n_uniqueUsers)\n",
    "print(\"number of uniqueEvents :%d\" % n_uniqueEvents)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 抽取出训练集，测试集中出现的event，保存新的events\n",
    "f_events = open(\"events.csv\", 'r')\n",
    "f_events_train_test = open(\"event_in_train_test.csv\", 'w')\n",
    "\n",
    "#第一行（列名字）\n",
    "f_events_train_test.write(f_events.readline())\n",
    "\n",
    "for line in f_events:    #对每条记录\n",
    "    cols = line.strip().split(\",\")\n",
    "    \n",
    "    if(cols[0] in uniqueEvents):\n",
    "        f_events_train_test.write(f_events.readline())\n",
    "\n",
    "f_events.close()\n",
    "f_events_train_test.close()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "collapsed": true
   },
   "source": [
    "# 2 聚类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/html": [
       "<div>\n",
       "<style>\n",
       "    .dataframe thead tr:only-child th {\n",
       "        text-align: right;\n",
       "    }\n",
       "\n",
       "    .dataframe thead th {\n",
       "        text-align: left;\n",
       "    }\n",
       "\n",
       "    .dataframe tbody tr th {\n",
       "        vertical-align: top;\n",
       "    }\n",
       "</style>\n",
       "<table border=\"1\" class=\"dataframe\">\n",
       "  <thead>\n",
       "    <tr style=\"text-align: right;\">\n",
       "      <th></th>\n",
       "      <th>event_id</th>\n",
       "      <th>user_id</th>\n",
       "      <th>start_time</th>\n",
       "      <th>city</th>\n",
       "      <th>state</th>\n",
       "      <th>zip</th>\n",
       "      <th>country</th>\n",
       "      <th>lat</th>\n",
       "      <th>lng</th>\n",
       "      <th>c_1</th>\n",
       "      <th>...</th>\n",
       "      <th>c_92</th>\n",
       "      <th>c_93</th>\n",
       "      <th>c_94</th>\n",
       "      <th>c_95</th>\n",
       "      <th>c_96</th>\n",
       "      <th>c_97</th>\n",
       "      <th>c_98</th>\n",
       "      <th>c_99</th>\n",
       "      <th>c_100</th>\n",
       "      <th>c_other</th>\n",
       "    </tr>\n",
       "  </thead>\n",
       "  <tbody>\n",
       "    <tr>\n",
       "      <th>0</th>\n",
       "      <td>244999119</td>\n",
       "      <td>3476440521</td>\n",
       "      <td>2012-11-03T00:00:00.001Z</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>2</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>7</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>1</th>\n",
       "      <td>2582345152</td>\n",
       "      <td>781585781</td>\n",
       "      <td>2012-10-30T00:00:00.001Z</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>1</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>8</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>2</th>\n",
       "      <td>1212611096</td>\n",
       "      <td>1426522332</td>\n",
       "      <td>2012-11-16T00:00:00.001Z</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>22</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>3</th>\n",
       "      <td>2584113432</td>\n",
       "      <td>613687941</td>\n",
       "      <td>2012-10-31T00:00:00.001Z</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>0</td>\n",
       "      <td>...</td>\n",
       "      <td>2</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>354</td>\n",
       "    </tr>\n",
       "    <tr>\n",
       "      <th>4</th>\n",
       "      <td>2912638473</td>\n",
       "      <td>3598071768</td>\n",
       "      <td>2012-10-18T00:00:00.001Z</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>NaN</td>\n",
       "      <td>1</td>\n",
       "      <td>...</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>0</td>\n",
       "      <td>3</td>\n",
       "    </tr>\n",
       "  </tbody>\n",
       "</table>\n",
       "<p>5 rows × 110 columns</p>\n",
       "</div>"
      ],
      "text/plain": [
       "     event_id     user_id                start_time city state  zip country  \\\n",
       "0   244999119  3476440521  2012-11-03T00:00:00.001Z  NaN   NaN  NaN     NaN   \n",
       "1  2582345152   781585781  2012-10-30T00:00:00.001Z  NaN   NaN  NaN     NaN   \n",
       "2  1212611096  1426522332  2012-11-16T00:00:00.001Z  NaN   NaN  NaN     NaN   \n",
       "3  2584113432   613687941  2012-10-31T00:00:00.001Z  NaN   NaN  NaN     NaN   \n",
       "4  2912638473  3598071768  2012-10-18T00:00:00.001Z  NaN   NaN  NaN     NaN   \n",
       "\n",
       "   lat  lng  c_1   ...     c_92  c_93  c_94  c_95  c_96  c_97  c_98  c_99  \\\n",
       "0  NaN  NaN    2   ...        0     0     0     0     0     0     0     0   \n",
       "1  NaN  NaN    1   ...        0     0     0     0     0     0     0     0   \n",
       "2  NaN  NaN    0   ...        0     0     0     0     0     0     0     0   \n",
       "3  NaN  NaN    0   ...        2     0     0     0     0     0     0     0   \n",
       "4  NaN  NaN    1   ...        0     0     0     0     0     0     0     0   \n",
       "\n",
       "   c_100  c_other  \n",
       "0      0        7  \n",
       "1      0        8  \n",
       "2      0       22  \n",
       "3      0      354  \n",
       "4      0        3  \n",
       "\n",
       "[5 rows x 110 columns]"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "#读取处理后的新数据\n",
    "X_train = pd.read_csv('event_in_train_test.csv')\n",
    "X_train.head()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<class 'pandas.core.frame.DataFrame'>\n",
      "RangeIndex: 13020 entries, 0 to 13019\n",
      "Columns: 110 entries, event_id to c_other\n",
      "dtypes: float64(2), int64(103), object(5)\n",
      "memory usage: 10.9+ MB\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "(13020, 110)"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "X_train.info()\n",
    "X_train.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(13020, 101)"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 删除前9列，对剩下的101列关键词做聚类\n",
    "X_train = X_train.drop(['event_id', 'user_id', 'start_time', 'city', 'state', 'zip', 'country','lat', 'lng'],axis=1)\n",
    "X_train.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/Users/karen/anaconda3/lib/python3.6/site-packages/sklearn/model_selection/_split.py:2026: FutureWarning: From version 0.21, test_size will always complement train_size unless both are specified.\n",
      "  FutureWarning)\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "((10416, 101), (2604, 101))"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "# 将训练集合拆分成训练集和校验集，在校验集上找到最佳的模型超参数（PCA的维数）\n",
    "X_train_part, X_val = train_test_split(X_train, train_size = 0.8, random_state = 0)\n",
    "X_train_part.shape, X_val.shape\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "# 一个参数点（聚类数据为K）的模型，在校验集上评价聚类算法性能\n",
    "def K_cluster_analysis(K, X_train):\n",
    "    start = time.time()\n",
    "    \n",
    "    print(\"K-means begin with clusters: {}\".format(K));\n",
    "    \n",
    "    #K-means,在训练集上训练\n",
    "    mb_kmeans = MiniBatchKMeans(n_clusters = K)\n",
    "    mb_kmeans.fit(X_train)\n",
    "    \n",
    "    # 预测结果\n",
    "    predict_result = mb_kmeans.predict(X_train)\n",
    "\n",
    "    # K值的评估标准\n",
    "    #常见的方法有轮廓系数Silhouette Coefficient和Calinski-Harabasz Index\n",
    "    #这两个分数值越大则聚类效果越好\n",
    "    #CH_score = metrics.calinski_harabaz_score(X_train,mb_kmeans.predict(X_train))\n",
    "    CH_score = metrics.silhouette_score(X_train, predict_result)\n",
    "  \n",
    "    end = time.time()\n",
    "    print(\"CH_score: {}, time elaps:{}\".format(CH_score, int(end-start)))\n",
    "    \n",
    "    return CH_score"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "K-means begin with clusters: 10\n",
      "CH_score: 0.29754854935562675, time elaps:4\n",
      "K-means begin with clusters: 20\n",
      "CH_score: 0.20645555476653088, time elaps:4\n",
      "K-means begin with clusters: 30\n",
      "CH_score: 0.13748033063066525, time elaps:4\n",
      "K-means begin with clusters: 40\n",
      "CH_score: 0.10467499953757303, time elaps:4\n",
      "K-means begin with clusters: 50\n",
      "CH_score: 0.0756707301740446, time elaps:4\n",
      "K-means begin with clusters: 60\n",
      "CH_score: 0.08222778734959303, time elaps:4\n",
      "K-means begin with clusters: 70\n",
      "CH_score: 0.06262706345271175, time elaps:5\n",
      "K-means begin with clusters: 80\n",
      "CH_score: 0.0559484664334728, time elaps:4\n",
      "K-means begin with clusters: 90\n",
      "CH_score: 0.05688780036556039, time elaps:4\n",
      "K-means begin with clusters: 100\n",
      "CH_score: 0.06389628806601579, time elaps:5\n"
     ]
    }
   ],
   "source": [
    "# 设置超参数（聚类数目K）搜索范围\n",
    "Ks = [10,20,30,40,50,60,70,80,90,100]\n",
    "CH_scores = []\n",
    "v_scores = []\n",
    "for K in Ks:\n",
    "    ch = K_cluster_analysis(K, X_train_part)\n",
    "    CH_scores.append(ch)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[<matplotlib.lines.Line2D at 0x1a0b1b66d8>]"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x1a0ae43be0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# 绘制不同PCA维数下模型的性能，找到最佳模型／参数（分数最高）\n",
    "plt.plot(Ks, np.array(CH_scores), 'b-')"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": [
    "从图中可以看出，最佳参数为K=10"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.3"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
